#include "cv.h"
#include "HandInterface.hpp"
#include <iostream>
#include "hiDependenciesForTestFramework.h"

using namespace cv;

const int PerPixelProbabilityTransformer::channels[2] = {0,1};
float PerPixelProbabilityTransformer::hranges[2] = {0,180};
float PerPixelProbabilityTransformer::sranges[2] = {0,256};

const float* PerPixelProbabilityTransformer::ranges[2] = { hranges, sranges };
int PerPixelProbabilityTransformer::histSize[] = { PerPixelProbabilityTransformer::hbins, PerPixelProbabilityTransformer::sbins};

void PerPixelProbabilityTransformer::getBackProjection( const cv::Mat& image, cv::Mat& backProjection ) {
	
	if ( histogram == NULL ) {
		CV_Error( CV_StsNullPtr,  "Histogram not set in perPixelProbabilityTransformer!"); //throws exception!
	}
	
	calcBackProject( &image, arrayCount, channels, *histogram, backProjection, ranges, histogramScale, histogramUniform);
	// arrayCount = 1, one array is used.
	// histogramUniform = true, the histogram is uniform
	
	//TODO RAT or test whether this helps
	filter->filterInPlace( backProjection );
}

PerPixelProbabilityTransformer::PerPixelProbabilityTransformer( cv::Ptr< AbstractFilter > filter )
: AbstractProbabilityTransformer(), filter(filter), histogram(0) {}

void PerPixelProbabilityTransformer::calcAndSetHist( const cv::Mat& image ) {
	
	histogram = new MatND();
	
	const int dimension = 2;
	const bool accumulativeCalc = false;
	
	cv::calcHist( &image, arrayCount, // arrayCount = 1, one array is used.
			 channels, Mat(), //  Mat() => do not use mask
			 *histogram, dimension, histSize, ranges, //dimension of histogram is two.
			 histogramUniform, // histogramUniform = true: the histogram is uniform
			 accumulativeCalc ); //calculation is not cumulative.

//The following can be enabled for testing
//#
//ifdef HI_TEST_VISUALISATION
//	double maxVal = 0;
//	minMaxLoc(*histogram, 0, &maxVal, 0, 0);
//	
//	int scale = 10;
//	Mat histImg = Mat::zeros(sbins*scale, hbins*10, CV_8UC3);
//	
//	for( int h = 0; h < hbins; h++ )
//		for( int s = 0; s < sbins; s++ )
//		{
//			float binVal = histogram->at<float>(h, s);
//			int intensity = cvRound(binVal*255/maxVal); //WAS bug : maxValue instead of maxVal
//			rectangle( histImg, Point(h*scale, s*scale), //WAS bug : cvRectangle instead
//					  Point( (h+1)*scale - 1, (s+1)*scale - 1),
//					  Scalar::all(intensity),
//					  CV_FILLED );
//		}
//	
//	HiVisualiser::windowMatrixMap["Histogram"] = histImg;
//	HiVisualiser::refreshWindow("Histogram");
//# endif
	
	
}

void PerPixelProbabilityTransformer::updateHist( const cv::Mat& image, const cv::Mat& mask ) {
	
	//MatND newHistogram = MatND();
	
	const int dimension = 2;
	const bool accumulativeCalc = true;
	
	calcHist( &image, arrayCount, // arrayCount = 1, one array is used.
				 channels, mask, //  Mat() => do not use mask
				 *histogram,
				 dimension, histSize, ranges, //dimension of histogram is two.
				 histogramUniform, // histogramUniform = true: the histogram is uniform
				 accumulativeCalc ); //calculation is cumulative.
	
	//FIXNOW exists? not documented
	//cvNormalizeHist( histogram, 1.0 );
	
	//*histogram = 0.5*(*histogram) + 0.5*newHistogram;
	//*histogram *= 0.99;
	//BROKEN! Need to update according to no. of points added (or normalise hist appropriately)
	
	//The following can be enabled for testing
//#ifdef HI_TEST_VISUALISATION
//	double maxVal = 0;
//	minMaxLoc(*histogram, 0, &maxVal, 0, 0);
//	std::cout << "pppt hist maxval=" << maxVal << std::endl;
//	
//	int scale = 10;
//	Mat histImg = Mat::zeros(sbins*scale, hbins*10, CV_8UC3);
//	
//	for( int h = 0; h < hbins; h++ )
//		for( int s = 0; s < sbins; s++ )
//		{
//			float binVal = histogram->at<float>(h, s);
//			int intensity = cvRound(binVal*255/maxVal); //WAS bug : maxValue instead of maxVal
//			rectangle( histImg, Point(h*scale, s*scale), //WAS bug : cvRectangle instead
//					  Point( (h+1)*scale - 1, (s+1)*scale - 1),
//					  Scalar::all(intensity),
//					  CV_FILLED );
//		}
//	
//	HiVisualiser::windowMatrixMap["Histogram"] = histImg;
//	HiVisualiser::refreshWindow("Histogram");
	
	//HiVisualiser::windowMatrixMap["HInwMask"] = image*mask;
	//HiVisualiser::refreshWindow("HInwMask");
	
//#endif
	
	
}

PerPixelProbabilityTransformer::~PerPixelProbabilityTransformer() {

	delete histogram;

}